home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 120_01.zip / DIO45.C < prev    next >
Text File  |  1993-06-01  |  9KB  |  324 lines

  1. /* HEADER: CUB120.07;
  2.    TITLE: DIO45;
  3.    VERSION: 1.45;
  4.    DATE: 12/00/1981;
  5.    DESCRIPTION: "Directed input/output simulation for BDS C.";
  6.    KEYWORDS: pipes,directed i/o;
  7.    SYSTEM: CP/M;
  8.    FILENAME: DIO45.C;
  9.    CRC: 26EE;
  10.    AUTHORS: Leor Zolman;
  11.    COMPILERS: BDS C;
  12. */
  13. /*
  14.     Directed I/O package for BDS C v1.45   LZ -- 12/81
  15.  
  16.     The following functions make up the directed I/O library:
  17.  
  18.     1. dioinit(&argc,argv)        Make this the first thing you do in
  19.                     your "main" function, to process
  20.                     redirection commands on the CP/M
  21.                     command line.
  22.  
  23.     2. getchar()            Gets a character from the keyboard,
  24.                     or from a directed input file if one
  25.                     was specified on the command line.
  26.  
  27.     3. putchar(c)            Puts a character out to the console,
  28.                     or to a directed output file if one
  29.                     was specified on the command line.
  30.  
  31.     4. dioflush()            Flushes directed output file, if open,
  32.                     and closes all directed I/O files (if
  33.                     any.) This must be called before your
  34.                     program exits or returns to CP/M.
  35.  
  36.     To activate redirection: Four special arguments may be given
  37.     on the command line to the generated COM file...
  38.  
  39.         >foo    causes "putchar" to place characters into the file
  40.             named "foo" instead of to the console.
  41.  
  42.         +foo    like >foo except that the characters are ALSO sent
  43.             to the console.
  44.  
  45.         <foo    causes "getchar" to return characters from the file
  46.             named "foo" instead of from the keyboard.
  47.  
  48.      command |prog    causes the standard output of the command specified in
  49.             "command" to be fed into the standard input of another
  50.             program, "prog". (BOTH "command" and "prog" must be
  51.             compiled with DIO)
  52.  
  53.     (Note that there must never be any spaces between >,+,< or | and the
  54.      corresponding filename.)
  55.  
  56.     When no "<" or "|" operator is used, standard input comes from the
  57.     console and all standard line editing characters are recognized (a 
  58.     new feature of v1.45). To indicate end-of-file, you must type
  59.         ^Z <CR>
  60.     (control-Z followed by    a carriage-return.)
  61.  
  62.     When no ">" or "|" operator is used, standard output goes to the
  63.     console.
  64.      
  65.     A program allowing redirection must have the following form:
  66.  
  67.         #include "bdscio.h"        /* standard header file    */
  68.         #include "dio.h"        /* directed I/O header    */
  69.  
  70.         ...                /* other externals, if any */
  71.  
  72.         main(argc,argv)
  73.         char **argv;
  74.         {
  75.             ...            /* declarations        */
  76.             dioinit(&argc,argv)    /* initialize redirection */
  77.             ...            /* body of program    */
  78.             dioflush();
  79.         }
  80.             
  81.     NOTES:
  82.  
  83.     0. The console input may be raw (unbuffered, one char. at a time) or
  84.        buffered (entire line must be typed before chars are returned,
  85.        allowing standard editing features, and characters come back one
  86.        at a time AFTER the entire line is typed). The default is raw; to
  87.        have buffered console input, uncomment the "#define BUF_CONS" line
  88.        in DIO.H and recompile this file and all files in your program.
  89.  
  90.     1. Redirection and pipes work only for TEXT. This mechanism should
  91.        not be used for binary data.
  92.  
  93.     2. Use "-f sio" to link the program; this ensures that the proper
  94.        versions of "getchar" and "putchar" are used. Do not define
  95.        your own "getchar" or "putchar", or things will get confused.
  96.  
  97.     3. Multiple pipes may be chained on one command line. For example,
  98.        the following command feeds the output of program "foo" into the
  99.        input of program "bar", the output of "bar" into the input of
  100.        program "zot", and the output of "zot" into a file called "output":
  101.  
  102.         A>foo arg1 |bar |zot arg2 arg3 >output <cr>
  103.  
  104.        "arg1" is an actual argument to "foo", and "arg2" and "arg3" are
  105.        actual arguments to "zot". This illustrates how actual arguments
  106.        may be interspersed with redirection commands. The programs see
  107.        the actual arguments, but command line preprocessing handled by the
  108.        "dioinit" function cause the programs to never need to know about
  109.        the redirection commands. Note that all three programs ("foo", "bar"
  110.        and "zot") must have been compiled and linked to use the "DIO"
  111.        package.
  112. */
  113.  
  114. #include "bdscio.h"
  115. #include "dio.h"
  116.  
  117. #define CON_INPUT    1        /* BDOS call to read console       */
  118. #define CON_OUTPUT    2        /* BDOS call to write to console   */
  119. #define CON_STATUS    11        /* BDOS call to interrogate status */
  120.  
  121. #define CONTROL_C    3        /* Quit character           */
  122. #define STDERR        4        /* Standard Error descriptor (sorry,
  123.                        Unix fans, 2 was already used.) */
  124. #define INPIPE        2        /* bit setting to indicate directed
  125.                        input from a temp. pipe file    */
  126. #define VERBOSE        2        /* bit setting to indicate output is to
  127.                        go to console AND directed output */
  128.  
  129. /* 
  130.     The "dioinit" function must be called at the beginning of the
  131.     "main" function:
  132. */
  133.  
  134. #define argc *argcp
  135.  
  136. dioinit(argcp,argv)
  137. int *argcp;
  138. char **argv;
  139. {
  140.     int i,j, argcount;
  141.  
  142.     _diflag = _doflag = _pipef = FALSE;  /* No directed I/O by default   */
  143.     _nullpos = &argv[argc];
  144.  
  145. #ifdef BUF_CONS
  146.     _conbuf[0] = 0;            /* no characters in buffer yet    */
  147.     _conbufp = _conbuf;        /* point to null buffer     */
  148. #endif
  149.  
  150.     argcount = 1;
  151.  
  152.     for (i = 1; i < argc; i++)    /* Scan the command line for > and < */
  153.     {
  154.         if (_pipef) break;
  155.         switch(*argv[i]) {
  156.  
  157.            case '<':        /* Check for directed input:    */
  158.             if (!argv[i][1]) goto barf;
  159.             if (fopen(&argv[i][1], _dibuf) == ERROR)
  160.             {
  161.                 fprintf(STDERR,"Can't open %s\n",&argv[i][1]);
  162.                 exit();
  163.             }
  164.             _diflag = TRUE;
  165.             if (strcmp(argv[i],"<TEMPIN.$$$") == 0)
  166.                  _diflag |= INPIPE;
  167.             goto movargv;
  168.  
  169.            case '|':    /* Check for pipe: */
  170.             _pipef++;
  171.             _pipedest = &argv[i][1]; /* save prog name for execl */
  172.             if (argv[i][1]) 
  173.             {
  174.                 argv[i] = ".TEMPOUT.$$$";  /* temp. output */
  175.                 _savei = &argv[i];
  176.             }
  177.             goto foo;
  178.  
  179.            case '+': 
  180.             _doflag |= VERBOSE;
  181.             
  182.          foo:   case '>':    /* Check for directed output    */
  183.         
  184.             if (!argv[i][1]) 
  185.             {
  186.             barf:   fprintf(STDERR,"Bad redirection/pipe specifier");
  187.                 exit();
  188.             }
  189.             unlink(&argv[i][1]);
  190.             if (fcreat(&argv[i][1], _dobuf) == ERROR)
  191.             {
  192.                    fprintf(STDERR,"Can't create %s\n",&argv[i][1]);
  193.                    exit();
  194.             }
  195.             _doflag++;
  196.  
  197.          movargv:    if (!_pipef) {
  198.                 for (j = i; j < argc; j++) argv[j] = argv[j+1];
  199.                 (argc)--;
  200.                 i--;
  201.                 _nullpos--;
  202.              } else {
  203.                 argc = argcount;
  204.                 argv[argc] = 0;
  205.              }
  206.             break;
  207.  
  208.             default:    /* handle normal arguments: */
  209.             argcount++;
  210.         }
  211.     }
  212. }
  213.  
  214.  
  215. #undef argc
  216.  
  217. /*
  218.     The "dioflush" function must be called before exiting the program:
  219. */
  220.  
  221. dioflush()
  222. {
  223.     if (_diflag)
  224.     {
  225.         fclose(_dibuf);
  226.         if (_diflag & INPIPE) unlink("tempin.$$$");
  227.     }
  228.  
  229.     if (_doflag)
  230.     {
  231.         putc(CPMEOF,_dobuf);
  232.         fflush(_dobuf);
  233.         fclose(_dobuf);
  234.         unlink("tempin.$$$");    /* in case previous pipe was aborted */
  235.         rename("tempout.$$$","tempin.$$$");
  236.         if (_pipef) 
  237.         {
  238.             *_savei = "<TEMPIN.$$$";
  239.             *_nullpos = NULL;
  240.             if (execv(_pipedest,_savei) == ERROR)
  241.             {
  242.                 fprintf(STDERR,"Broken pipe\n");
  243.                 exit();
  244.             }
  245.         }
  246.     }
  247. }
  248.  
  249.  
  250. /*
  251.     This version of "getchar" replaces the regular version when using
  252.     directed I/O. Note that the "BUF_CONS" defined symbol (in DIO.H)
  253.     controls whether the console input is to be raw or buffered (see
  254.     item 0. in NOTES above)
  255. */
  256.  
  257. getchar()
  258. {
  259.     char c;
  260.  
  261.     if (_diflag) {
  262.         if ((c = getc(_dibuf)) == '\r') c = getc(_dibuf);
  263.     }
  264.     else
  265.  
  266. #ifdef BUF_CONS        /* For buffered console input, get a line of text   */
  267.     {        /* from the BDOS (using "gets"), & insert newline:  */
  268.         if (!*_conbufp) {   
  269.             gets(_conbufp = _conbuf);
  270.             _conbuf[strlen(_conbuf) + 1] = '\0';
  271.             _conbuf[strlen(_conbuf)] = '\n';
  272.         }
  273.         c = *_conbufp++;
  274.     }
  275. #else            /* for raw console input, simulate normal "getchar": */
  276.         if ((c = bdos(CON_INPUT)) == CONTROL_C) exit();
  277. #endif
  278.  
  279.     if (c == CPMEOF) return EOF;         /* Control-Z is EOF key     */
  280.  
  281.     if (c == '\r') 
  282.     {
  283.         c = '\n';
  284. #ifndef BUF_CONS
  285.         if (!_diflag) bdos(2,'\n');  /* echo LF after CR to console */
  286. #endif
  287.     }
  288.     return c;
  289. }
  290.  
  291.  
  292. /*
  293.     This version of "putchar" replaces the regular version when using
  294.     directed I/O:
  295. */
  296.  
  297. putchar(c)
  298. char c;
  299. {
  300.     if (_doflag)
  301.     {
  302.         if (c == '\n') putc('\r',_dobuf);
  303.         if(putc(c,_dobuf) == ERROR)
  304.         {
  305.             fprintf(STDERR,"File output error; disk full?\n");
  306.             exit();
  307.         }
  308.         if (!(_doflag & VERBOSE)) return;
  309.     }
  310.  
  311.     if (bdos(CON_STATUS) && bdos(CON_INPUT) == CONTROL_C) exit();
  312.     if (c == '\n') bdos(CON_OUTPUT,'\r');
  313.     bdos(CON_OUTPUT,c);
  314. }
  315.             argcount++;
  316.         }
  317.     }
  318. }
  319.  
  320.  
  321. #undef argc
  322.  
  323. /*
  324.     The "dioflush" function must be called before exiting the pr